import { cloneDeep } from 'lodash';
import React, { useLayoutEffect, useRef, useState } from 'react';
import CssMotion from './CssMotion';
import type { YmCssMotionListProps } from './interface';
import {
  STATUS_ADD,
  STATUS_KEEP,
  STATUS_REMOVED,
  diffDataSource,
} from './util/diff';

function CssMotionList(props: YmCssMotionListProps) {
  const {
    componentProps,
    rowKey,
    dataSource,
    children,
    onVisibleChanged,
    onAllRemoved,
    ...restProps
  } = props;
  const { tagName, ...restComponentProps } = componentProps || {};
  const [dataSourceState, setDataSourceState] = useState<
    YmCssMotionListProps['dataSource']
  >([]);
  const dataSourceStateRef = useRef<YmCssMotionListProps['dataSource']>([]);

  // useEffect：会出问题？？？
  useLayoutEffect(() => {
    const prevDataSource = (dataSourceStateRef.current || []).filter(
      (data) => data.status !== STATUS_REMOVED,
    );
    // console.log('--prevDataSource--dataSource--:', cloneDeep(prevDataSource), cloneDeep(dataSource))
    const newDataSource = diffDataSource(
      prevDataSource,
      cloneDeep(dataSource),
      rowKey,
    );
    dataSourceStateRef.current = newDataSource;

    // console.log('--useLayoutEffect--newDataSource--:', dataSourceStateRef.current);
    //注： useLayoutEffect(() => {},[[dataSourceStateRef.current]) 有时候不会执行，所以setDataSourceState做兼容
    setDataSourceState(newDataSource);
  }, [dataSource]);

  useLayoutEffect(() => {
    // console.log('--未监听到变化--dataSourceStateRef.current----:', dataSourceStateRef.current);
    setDataSourceState(dataSourceStateRef.current);
  }, [dataSourceStateRef.current]);

  const Component = tagName ? tagName : React.Fragment;

  //注：markRemoved同步多次执行 setDataSourceState是不行的，dataSourceState无法及时更新
  function markRemoved(removedKey: React.Key): number {
    const newDataSourceState = dataSourceStateRef.current.map((data) => {
      if (data[rowKey] === removedKey) {
        return {
          ...data,
          status: STATUS_REMOVED,
        };
      }
      return data;
    });
    dataSourceStateRef.current = newDataSourceState;

    // setDataSourceState(newDataSourceState);
    const notRemovedDataSource = newDataSourceState.filter(
      (data) => data.status !== STATUS_REMOVED,
    );
    // console.log('-----notRemovedDataSource------:', notRemovedDataSource)
    return notRemovedDataSource.length;

    //注：//visible: onVisibleChange肯定在ontransitionend/onanimationend之后执行
    // const notRemovedDataSource = dataSourceState.filter((data) => data.status !== STATUS_REMOVE);
    // setDataSourceState(notRemovedDataSource);
    // return notRemovedDataSource.length;
  }

  return (
    <Component {...restComponentProps}>
      {dataSourceState &&
        dataSourceState.length > 0 &&
        dataSourceState.map((data) => {
          const currVisible =
            data.status === STATUS_ADD || data.status === STATUS_KEEP;
          return (
            <CssMotion
              {...restProps}
              key={data[rowKey]}
              visible={currVisible}
              childrenFnParams={{ listItem: data }}
              onVisibleChanged={(changedVisible) => {
                onVisibleChanged?.(changedVisible, data);

                if (!changedVisible) {
                  const restKeysCount = markRemoved(data[rowKey]);

                  if (restKeysCount === 0) {
                    onAllRemoved?.();
                  }
                }
              }}
            >
              {({ visible, style, className, listItem }, motionRef) => {
                return children(
                  { visible, style, className, listItem },
                  motionRef,
                );
              }}
            </CssMotion>
          );
        })}
    </Component>
  );
}

export default CssMotionList;
